<?php

/**
 * 优时通 JDK
 * @author chenshubo
 */
namespace App\Service\VendorClient\ShopystApi;
use App\Service\Code\Normal;
use App\Service\BaseService;
use Service\AppService\IdService;
use App\Service\TaskServer\TaskWorker;
use App\Model\PssModel\ServiceConfig;

class ShopystApiClient extends BaseService
{
    private $parter_id;
    private $clientConfig;
    private $secret_key;

    /**
     * 初始参数
     */
    public function __construct($apiBody=[]) 
    {
        $this->clientConfig = $apiBody;
        $this->parter_id    = $this->clientConfig['parter_id'];
        $this->secret_key   = $this->clientConfig['secret_key'];
    }
    
    protected function get_request_id(){
        return [
            'request_id'    => (string)IdService::instance()->getOtherID(),
            'timestamp'     => date('Y-m-d H:i:s' , time())
        ];
    }
    
    /**
     * 创建订单
     */
    public function createOrder( $param = [] ) 
    {
        $orderInfo  = $param['supplierOrder'];
        $goodsList  = $param['orderGoods'];
        $order      = $param['order'];
        $binfo      = $param['binfo'];
        //运费
        $deliver_money  = $orderInfo['deliver_money'];
        
        //商品下单组
        $orderGoodsList = [];
        $productAmt     = $TaxAmt = 0 ;
        foreach ($goodsList as $key => $item )
        {
            //卖价
            $price          = $item['price'];
            //商品购买规格数量
            $spec_num       = $item['spec_num'];
            //商品购买数量(下单数量 X 起售数量)
            $quantity       = $item['quantity'];
            //实际购买数量
            $buyAcount      = $spec_num * $quantity ;
            //商品单价包含税金
            if( $key == 0 ) {
                $dev_money   = bcdiv((string)$deliver_money, (string)$quantity,3);
                $dev_money   = bcmul((string)$dev_money,'100',1);
                $dev_money   = bcdiv((string)ceil($dev_money),'100',2);
                $price       = bcadd((string)$price, (string)$dev_money,2);
            }
            
            //商品税率
            $tax                = $item['tax_rate'];
            $tax_rate           = bcadd((string)$tax,'1.0000',4);

            //单价含税单价需要把第三位往上收取，不能单独不含税价和税金分开计算，需要做减法
            $singlePrice        = bcdiv((string)$price, (string)$spec_num,3);
            $singlePrice        = bcmul((string)$singlePrice,'100',1);
            $singlePrice        = bcdiv((string)ceil($singlePrice),'100',2);
            
            //不含税价格
            $notTaxGoodsSinglePrice = bcdiv((string)$singlePrice, $tax_rate,3);
            $notTaxGoodsSinglePrice = bcmul((string)$notTaxGoodsSinglePrice,(string)'100',1);
            $notTaxGoodsSinglePrice = bcdiv((string)ceil($notTaxGoodsSinglePrice),'100',2);
            
            $buyNum             = $spec_num * $quantity;
            $goodsTotalPrice    = bcmul((string)$notTaxGoodsSinglePrice,(string)$buyNum,2);
            
            //商品关税当前币种最小单位（分）
            $goodsCustomsTax    = bcsub((string)$singlePrice,(string)$notTaxGoodsSinglePrice,2);
            $taxAll             = bcmul($goodsCustomsTax,(string)$buyNum,2);
            
            //商品组
            $orderGoodsList[] = [
                'SKUNo'                 => $item['supplier_skucode'],
                'Qty'                   => $buyAcount,
                //向海关做支付申报的商品单价，即不含税的实际售价，单位为元，最多 2 位小数
                'DeclarationUnitPrice'  => $notTaxGoodsSinglePrice,
                //订单中此商品的海关跨境综合税金小计，单位为元，最多 2 位小数
                'SummaryTaxAmt'         => $taxAll,
            ];
            
            $productAmt = bcadd((string)$productAmt,(string)$goodsTotalPrice,2);
            $TaxAmt = bcadd((string)$TaxAmt,(string)$taxAll ,2);
        }
        
        //向海关申报的订单的实际支付金额 = 向海关申报的商品货款总额 + 向海关申报的运费金额 + 向海关申报的保费金额 + 向海关申报的订单跨境综合税总的税金 - 向海关申报的订单优惠抵扣金额
        $ActualPaidAmt  = bcadd((string)$TaxAmt,(string)$productAmt,2);
        
        //下单支付的时候支付信息
        $apply_extends  = @json_decode($orderInfo['apply_extends'],true);
        $payTime        = empty($order['payTime']) ? $orderInfo['pay_time'] :$order['payTime'];
        //支付时间
        $pay_time       = $payTime ? $payTime : time();
        $pay_time       = date('Y-m-d H:i:s',$payTime);
        
        //支付流水号
        $pay_sn         = $order['paySerial']??$orderInfo['pay_sn'];
        
        //是否发起申报,保税商品需发起申报，一般贸易和海外直邮不需要发起申报
        $goods_type  = current(array_unique(array_column($goodsList,'goods_type')));
        $PaymentDeclarationByMerchant = $goods_type == 1 ? true : false;
        
        //支付公司
        $payCommanyCode = $apply_extends['payCommanyCode']??'';
        $PayCompanyCode = $order['payCommanyCode'] ? $order['payCommanyCode'] : $payCommanyCode ;
        //电商平台
        $enterpriseNum  = $apply_extends['enterpriseNum']??'';
        $EBPCompanyCode = $order['enterpriseNum'] ? $order['enterpriseNum'] : $enterpriseNum ;
        
        //获取支付方式配置
        $pay_value = ServiceConfig::instance()->getConfigByEventsValue('shopyst', ServiceConfig::TYPE_PAY, $PayCompanyCode);
        if( empty($pay_value) ) {
            return Normal::returnCode(Normal::FAIL,"支付公司编码：【{$PayCompanyCode}】未映射，请联系管理员处理");
        }
        
        //获取电商平台映射配置
        $channel_value = ServiceConfig::instance()->getConfigByEventsValue('shopyst', ServiceConfig::TYPE_CHANNEL, $EBPCompanyCode);
        if( empty($channel_value) ) {
            return Normal::returnCode(Normal::FAIL,"支付电商平台编码：【{$EBPCompanyCode}】未映射，请联系管理员处理");
        }        
        
        //优惠金额
        $discount_money = bcsub((string)$ActualPaidAmt,(string)$orderInfo['real_total_money'],2);
        if( $orderInfo['province'] == '海南省' ) {
            if( $orderInfo['city'] == '直辖县' ) {
                $orderInfo['city'] = $orderInfo['district'];
            }
        }
        //创建订单数据
        $data = [
            //下单基础信息
            'ParterOrderNo'                 => $orderInfo['supplier_dsn'],
            'IdCardNo'                      => $orderInfo['buyer_idcard'],
            'IdCardName'                    => $orderInfo['buyer_realname'],
            'ContactName'                   => $orderInfo['receive_name'],
            'Mobile'                        => $orderInfo['recveive_phone'],
            'Province'                      => $orderInfo['province'],
            'City'                          => $orderInfo['city'],
            'District'                      => $orderInfo['district'],
            'StreetAddress'                 => $orderInfo['receive_address'],
            'Remark'                        => $orderInfo['order_remark'],
        
            //如果商户在优时通平台有账户余额，是否不允许使用账户余额来支付此新创建的订单；为 True 则表示不允许使用余额来支付
            'NotPayByBalance'               => false,
            //如果商户在优时通平台有预购锁库的库存，是否不允许使用预购的库存来生成此订单；为 True 则表示不允许使用预购库存来生成此订单
            'NotUsePreOrderedInventory'     => false,
        
            //下游商户已申报的订单参数
            'PaymentDeclarationByMerchant'  => $PaymentDeclarationByMerchant,
        
            //向海关做支付申报的支付流水号
            'PaymentTransNo'                => $pay_sn,
            //实际支付时间，格式为yyyy-MM-dd HH:mm:ss；
            'PaidOn'                        => $pay_time,
        
            //向海关申报的支付企业在优时通平台的编码
            'PayCompanyCode'                => $pay_value,
            //向海关申报的电商平台企业在优时通平台的编码
            'EBPCompanyCode'                => $channel_value,
        
            //向海关申报的商品货款总额，单位为元，最多 2 位小数
            'ProductAmt'                    => $productAmt,
            //向海关申报的运费金额，单位为元，最多 2 位小数
            'ShippingFeeAmt'                => '0.00',
            //向海关申报的保费金额，单位为元，最多 2 位小数
            'InsuredFeeAmt'                 => '0.00',
            //向海关申报的订单优惠抵扣金额，单位为元，最多 2位小数；
            'DiscountAmt'                   => $discount_money,
            //向海关申报的订单跨境综合税总的税金，单位为元，最多 2 位小数
            'TaxAmt'                        => $TaxAmt,
            //向海关申报的订单的实际支付金额，单位为元，最多2 位小数，此字段金额需要等 于 ProductAmt +ShippingFeeAmt +InsuredFeeAmt +TaxAmt - DiscountAmt
            'ActualPaidAmt'                 => $orderInfo['real_total_money'],
            /* //指定此订单做海关申报时所用的电商企业，可以留空不填,则优时通使用平台自己的电商企业来进行订单申报；
             //这里的 Code 是电商企业在优时通平台的一个特有编码，所以需要先联系优时通平台为此电商企业在优时通平台生成一个编码；
            'EBCCompanyCode'                => 'YYYYY',
            'TaxGuarantee'                  => 'EBC',
            //此字段指定订单是否为商家自有寄售库存的订单，若留空不填的话默认为 false
            'ConsignmentOrder'              => False, */
            //商品组
            'Items'                         => $orderGoodsList,
        ];

        $request_info = $this->get_request_id();
        $data = [$data];
        $sign = $this->getSign([
            'data'          => $data,
            'request_id'    => $request_info['request_id'],
            'timestamp'     => $request_info['timestamp']
        ]);
        //请求参数
        $requestParam = array_merge(self::getCommonParam($request_info),[
            'method'    => 'createOrder',
            'sign'      => $sign,
            'data'      => self::getJsonStr($data)
        ]);
        
        //开始请求
        $res = $this->execute($requestParam);
        if( $res['code'] == Normal::SUC ) {
            $resCurrent = current($res['data']);
            if( isset($resCurrent['Success']) && $resCurrent['Success'] == true ) {
                return Normal::returnCode(Normal::SUC,"订单推送成功",[
                    'thirdpart_order_sn' => $resCurrent['OrderInfo']['OrderNo']
                ]);
            } else {
                $message = isset($resCurrent['Message']) ? $resCurrent['Message'] : '优时通订单推送创建失败';
                return Normal::returnCode(Normal::FAIL,$message);
            }
        }
        return $res;
    }
        
    /**
     * 获取商品列表
     */
    public function queryGoodsList( $params = [] ) 
    {
        $page = $params['page'] ?? 1;
        $page = $page >= 1 ? ($page -1 ) : 0;
        $data = [
            'PageIndex'     => $page,
            'OnlySKUHasQ4S' => $params['isSale'] ?? true,
        ];
        sleep(1);
        $request_info = $this->get_request_id();
        $sign = $this->getSign([
            'data'          => $data,
            'request_id'    => $request_info['request_id'],
            'timestamp'     => $request_info['timestamp']
        ]);
        
        //请求参数
        $requestParam = array_merge(self::getCommonParam($request_info),[
            'method'    => 'goodsLists',
            'sign'      => $sign,
            'data'      => self::getJsonStr($data)
        ]);
        
        return $this->execute($requestParam);
    }
    
    /**
     * 获取指定商品信息
     */
    public function queryGoodsInfo( $params = [] ) {
        
        $data = $params['skuList'] ?? [] ;
        $request_info = $this->get_request_id();
        $sign = $this->getSign([
            'data'          => $data,
            'request_id'    => $request_info['request_id'],
            'timestamp'     => $request_info['timestamp']
        ]);
        
        //请求参数
        $requestParam = array_merge(self::getCommonParam($request_info),[
            'method'    => 'queryGoodsInfo',
            'sign'      => $sign,
            'data'      => self::getJsonStr($data)
        ]);
        
        return $this->execute($requestParam);
    }
    
    /**
     * 获取指定订单信息
     */
    public function queryOrder( $params = [] ) {
        $data = $params['orderSnLists'] ?? [] ;
        $request_info = $this->get_request_id();
        $sign = $this->getSign([
            'data'          => $data,
            'request_id'    => $request_info['request_id'],
            'timestamp'     => $request_info['timestamp']
        ]);
        
        //请求参数
        $requestParam = array_merge(self::getCommonParam($request_info),[
            'method'    => 'queryOrder',
            'sign'      => $sign,
            'data'      => self::getJsonStr($data)
        ]);
        
        return $this->execute($requestParam);
    }
    
    /**
     * 取消订单
     */
    public function cancelOrder( $params = [] ) 
    {
        $orderInfo = $params['supplierOrder'];
        $data = [
            (string)$orderInfo['supplier_dsn']
        ];
        
        $request_info = $this->get_request_id();
        $sign = $this->getSign([
            'data'          => $data,
            'request_id'    => $request_info['request_id'],
            'timestamp'     => $request_info['timestamp']
        ]);
        
        //请求参数
        $requestParam = array_merge(self::getCommonParam($request_info),[
            'method'    => 'cancelOrder',
            'sign'      => $sign,
            'data'      => self::getJsonStr($data)
        ]);
        
        //开始请求
        $res = $this->execute($requestParam);
        if( $res['code'] == Normal::SUC ) {
            $resCurrent = current($res['data']);
            if( $resCurrent['Success'] == true ) {
                return Normal::returnCode(Normal::SUC,$resCurrent['Message']);
            } else {
                if( in_array($resCurrent['Message'],['订单不存在，或已经作废了']) ) {
                    return Normal::returnCode(Normal::SUC,'订单取消操作成功');
                }
            }
            return Normal::returnCode(Normal::FAIL,$resCurrent['Message']);
        }
        return $res;
    }
    
    /**
     * 获取商户的账户信息
     */
    public function queryAccount( $params = [] ) {
        
        $data = [] ;
        $request_info = $this->get_request_id();
        $sign = $this->getSign([
            'data'          => $data,
            'request_id'    => $request_info['request_id'],
            'timestamp'     => $request_info['timestamp']
        ]);
        
        //请求参数
        $requestParam = array_merge(self::getCommonParam($request_info),[
            'method'    => 'queryAccount',
            'sign'      => $sign,
            'data'      => self::getJsonStr($data)
        ]);
        
        return $this->execute($requestParam);
    }
    
    /**
     * 获取签名公共参数
     * @return array
     */
    private function getCommonParam($request_info) {
        return [
            'parter_id'     => $this->parter_id,
            'request_id'    => $request_info['request_id'],
            'timestamp'     => $request_info['timestamp'],
            'secret_key'    => $this->secret_key,
        ];
    }
    
    /**
     * 获取sign参数
     */
    private function getSign( $param = [] ) {
        $arr = [
            'secret_key'    => $this->secret_key,
            'parter_id'     => $this->parter_id,
            'request_id'    => $param['request_id'],
            'timestamp'     => $param['timestamp'],
            'data'          => $this->getJsonStr($param['data'])
        ];
        
        $implode = [];
        foreach( $arr as $key => $val ) {
            $implode[] = "{$key}={$val}";
        }
        
        $string = implode("&",$implode);
        $string = str_replace("\r\n", '', $string);
        return strtolower(md5($string));
    }
    
    /**
     * 获取json数据
     * @param array $data
     */
    private function getJsonStr( $data = [] )  {
        return json_encode($data,JSON_UNESCAPED_UNICODE);
    }
    
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function execute( $param = [] )  {
        
        $domain = $this->clientConfig['baseurl'];
        if( !isset($this->clientConfig[$param['method']])) {
            return Normal::returnCode(Normal::FAIL,"调用方法不存在，请核对！");
        }
        $method = $param['method'];
        $url = $domain.$this->clientConfig[$method];
        unset($param['method']);
        unset($param['secret_key']);
        
        $parameter = [
            [
                'tag'       => 'shopyst_'.$method,
                'uid'       => $this->get_request_id(),
                'url'       => $url,
                'data'      => $param,
                'method'    => 'post',
                'format'    => 'x-www-form-urlencoded',
                'header'    => [],
            ],
        ];
        
        if( in_array($method,['goodsLists']) ) {
            $resTask = TaskWorker::instance()->addTask($parameter,'handleDiableTask');
        } else {
            $resTask = TaskWorker::instance()->addTask($parameter);
        }
        
        
        $resTask = current($resTask);
        $result  = @json_decode($resTask['response']['result'],true);
        if( isset($result['error']) && !$result['error'] ) {
            return Normal::returnCode(Normal::SUC,"操作成功",$result['data']);
        }
        
        $message = isset($result['message']) ? $result['message'] : '';
        return Normal::returnCode(Normal::FAIL,$message);
    }
}